package com.yuuko.yuukoapi.project.limb.controller

import cn.dev33.satoken.secure.BCrypt
import com.yuuko.yuukoapi.common.exception.BizException
import com.yuuko.yuukoapi.common.exception.ErrorCode
import com.yuuko.yuukoapi.common.request.PageParam
import com.yuuko.yuukoapi.common.response.AjaxResult
import com.yuuko.yuukoapi.common.response.None
import com.yuuko.yuukoapi.common.utils.AesEncryptUtils
import com.yuuko.yuukoapi.framework.extension.findPage
import com.yuuko.yuukoapi.project.limb.doman.entity.Device
import com.yuuko.yuukoapi.project.limb.doman.entity.DeviceModel
import com.yuuko.yuukoapi.project.limb.doman.entity.by
import com.yuuko.yuukoapi.project.limb.doman.entity.dto.DeviceListSpec
import com.yuuko.yuukoapi.project.limb.doman.entity.dto.DeviceUpdateInput
import com.yuuko.yuukoapi.repository.limb.DeviceRepository
import org.babyfish.jimmer.Page
import org.babyfish.jimmer.sql.ast.mutation.SaveMode
import org.babyfish.jimmer.sql.kt.fetcher.newFetcher
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/limb/device")
class DeviceController(
    val deviceRepository: DeviceRepository
) {
    @GetMapping("/list")
    fun getDeviceModelList(
        page: PageParam,
        spec: DeviceListSpec
    ): AjaxResult<Page<Device>> {
        val result = deviceRepository.findPage(page, spec, newFetcher(Device::class).by {
            allScalarFields()
            model { allScalarFields() }
        })
        return AjaxResult.ok(result)
    }

    @PostMapping
    fun createDeviceModel(
        @RequestBody input: DeviceUpdateInput
    ): AjaxResult<None?> {
        deviceRepository.save(input, SaveMode.INSERT_ONLY)
        return AjaxResult.ok()
    }

    @PutMapping("/{id}")
    fun updateDeviceModel(@PathVariable id: String, @RequestBody input: DeviceUpdateInput): AjaxResult<None?> {
        deviceRepository.save(input.toEntity { this.id = id }, SaveMode.UPDATE_ONLY)
        return AjaxResult.ok()
    }

    @DeleteMapping("/{id}")
    fun deleteDeviceModel(@PathVariable id: String): AjaxResult<None?> {
        deviceRepository.deleteById(id)
        return AjaxResult.ok()
    }

    @GetMapping("/generate/{id}")
    fun generateDeviceModel(@PathVariable id: String): AjaxResult<String> {
        val device = deviceRepository.findNullable(id) ?: throw BizException(ErrorCode.ID_NOT_FOUND)
        val result = AesEncryptUtils.encryptDeviceCode("${device.id};${device.code}")
        return AjaxResult.ok(result)
    }
}